package com.appengine.news.ui.controller;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Logger;

import javax.jdo.PersistenceManager;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import com.appengine.news.Constants;
import com.appengine.news.entity.RssItemEntity;
import com.appengine.news.ui.model.ReadModel;
import com.appengine.news.utils.HTMLSanitiser;
import com.appengine.news.utils.StringUtils;
import com.google.appengine.api.datastore.Text;
import com.google.appengine.api.labs.taskqueue.Queue;
import com.google.appengine.api.labs.taskqueue.QueueFactory;
import com.google.appengine.api.labs.taskqueue.TaskOptions;
import com.google.appengine.api.labs.taskqueue.TaskOptions.Builder;

/**
 * Read page controller
 * 
 * @author Aliaksandr_Spichakou
 * 
 */
public class ReadController extends AbstractUIController {
	/**
	 * 
	 */
	private static final long serialVersionUID = -5310256052091349440L;
	private static final Logger log = Logger.getLogger(ReadController.class
			.getName());
	private ReadModel model;	
	private HttpSession session;
	private String command;
	private List<Long> history = new ArrayList<Long>();;
	private int historyIndex=-1;
	private boolean forwardAvailable;
	private boolean backAvaliable;

	public ReadController(HttpServletRequest request) {	
		super(request);
	}
	/**
	 * Do controll
	 */
	public void doJob()
	{
		log.entering(ReadController.class.getName(), "doJob");		
		dispatchCommands(request);		
		final RssItemEntity rssItem = getRssItem();
		isBackAvailable();		
		isForwardAvailable();
		final ReadModel m = new ReadModel();
		model = fillModel(rssItem, m);	
		log.exiting(ReadController.class.getName(), "doJob");
	}
	/**
	 * Get RSS item from DB
	 * @return
	 */
	private RssItemEntity getRssItem() {
		log.entering(ReadController.class.getName(), "getRssItem");
		String query;
		if((historyIndex>=0) && (historyIndex<history.size()))		
		{
			query = "select from " + RssItemEntity.class.getName() + " where id==" + history.get(history.size()-2-historyIndex);
		}
		else
		{
			query = "select from " + RssItemEntity.class.getName() + " where readedFlag==null order by modified asc range 0,1";
		}				
		final PersistenceManager pm = getPersistenceManager();

		final List<RssItemEntity> items = (List<RssItemEntity>) pm.newQuery(query).execute();
		RssItemEntity item=null;
		if(!items.isEmpty())
		{
			item = items.get(0);			
		}
		
		if(item!=null)
		{
			final Long id = item.getId();
			if(!history.contains(id))
			{
				history.add(id);
			}
		}
		
		session.setAttribute(HISTORY_SESSION_ATTRIBUTE, history);
		log.exiting(ReadController.class.getName(), "getRssItem");
		return item;
	}

	/**
	 * Fill UI model
	 */
	protected ReadModel fillModel(RssItemEntity item, ReadModel m) {
		log.entering(ReadController.class.getName(), "fillModel");		
		if(item==null)
		{
			log.exiting(ReadController.class.getName(), "fillModel");
			return m;
		}
		m.setId(item.getId());

		final Text ttl = item.getTitle();
		if (ttl != null) {
			String title = ttl.getValue();
			title = HTMLSanitiser.stripInvalidMarkup(title, false);
			m.setTitle(title);
		}

		String author = item.getAuthorName();
		if(!StringUtils.isEmpty(author))
		{
			author = HTMLSanitiser.stripInvalidMarkup(author, false);
			m.setAuthor(author);
		}
		
		final Date modified = item.getModified();
		if (modified != null) {
			m.setModified(modified.toString());
		}
		final Text sum = item.getSummury();
		String summury = "";
		if (sum != null) {
			summury = sum.getValue();
		}
		// summury = HTMLSanitiser.encodeInvalidMarkup(summury,false);
		summury = HTMLSanitiser.stripInvalidMarkup(summury, false);
		m.setSummury(summury);
		m.setLink(item.getLink());

		log.exiting(ReadController.class.getName(), "fillModel");
		return m;
	}

	/**
	 * Despatch commands
	 * 
	 * @param request
	 */
	private void dispatchCommands(HttpServletRequest request) {
		log.entering(ReadController.class.getName(), "dispatchCommands");
		final PersistenceManager pm = getPersistenceManager();
		command = request.getParameter(Constants.COMMAND);
		final String id2mark = request.getParameter(Constants.VALUE_ID);
		if (Constants.MARK_AS_READED_COMMAND.equalsIgnoreCase(command)) {
			if (id2mark != null) {
				final Long parseString2Long = StringUtils.parseString2Long(id2mark);
				if(parseString2Long==null)
				{
					log.exiting(ReadController.class.getName(), "dispatchCommands");
					return;
				}				
				final String query = "select from "
						+ RssItemEntity.class.getName() + " where id=="
						+ id2mark;
				final List<RssItemEntity> items = (List<RssItemEntity>) pm
						.newQuery(query).execute();
				if (!items.isEmpty()) {
					final RssItemEntity item = items.get(0);
					item.setReadedFlag("y");
					pm.makePersistent(item);
					pm.flush();
					pm.close();
				}
			}
			log.exiting(ReadController.class.getName(), "dispatchCommands");
			return;
		}
		if (Constants.SEND_TO_COMMAND.equalsIgnoreCase(command)) {			
			final List<String> emails = cfg.getPostEmail();
			if(emails==null || emails.isEmpty())
			{
				log.exiting(ReadController.class.getName(), "dispatchCommands");
				return;
			}
			
			final Iterator<String> iterator = emails.iterator();
			while(iterator.hasNext())
			{
				final String next = iterator.next();
				final Queue queue = QueueFactory.getQueue(DEFAULT_QUEUE);
				TaskOptions options = Builder.url(MAIL_TASK);
				options = options.param(VALUE_IDS, id2mark);			
				options = options.param(VALUE_MAILTO, next);
				queue.add(options);	
			}
						
			log.exiting(ReadController.class.getName(), "dispatchCommands");
			return;

		}
		final String historyIndex = request.getParameter(VALUE_HISTORY_INDEX);		
		int parseString2Int = StringUtils.parseString2Int(historyIndex);
		this.historyIndex=parseString2Int;
		if (Constants.BACK_COMMAND.equalsIgnoreCase(command)) {						
			this.historyIndex++;
		}
		if (Constants.FORWARD_COMMAND.equalsIgnoreCase(command)) {
			this.historyIndex--;
		}
		log.exiting(ReadController.class.getName(), "dispatchCommands");
	}

	/**
	 * Get model
	 * 
	 * @return
	 */
	public ReadModel getModel() {
		return model;
	}
	/**
	 * Set HttpSession
	 * @param session
	 */
	public void setSession(HttpSession session) {
		this.session = session;
		final List<Long> hst = (List<Long>)session.getAttribute(Constants.HISTORY_SESSION_ATTRIBUTE);
		if(hst!=null)
		{
			history=hst;
		}
	}
	
	public List<Long> getHistory()
	{
		return history;
	}
	/**
	 * Get history index
	 * @return
	 */
	public int getHistoryIndex()
	{
		return historyIndex;
	}
	
	public boolean renderBack()
	{
		return backAvaliable;
	}
	public boolean renderForward()
	{
		return forwardAvailable;
	}
	
	private void isBackAvailable()
	{		
		final int index=historyIndex+2;
		backAvaliable = index<history.size() && history.size()>0;		
	}
	
	private void isForwardAvailable()
	{
		//final int index=historyIndex-1;
		forwardAvailable = historyIndex>=0;
	}
}
